<?php

class WritableRecordFactory extends ReadableRecordFactory {
	
	public function beginTransaction() {
		return $this->getDbHandle()->beginTransaction();
	}

	public function commit() {
		return $this->getDbHandle()->commit();
	}

	public function rollBack() {
		return $this->getDbHandle()->rollBack();
	}

	public function delete($class_name, $where_sql = "", array $where_values = array()) {
		$table_name = $this->getTableName($class_name);
		$sql = "DELETE FROM `$table_name` WHERE $where_sql";
		$statement = $this->getDbHandle()->prepare($sql);
		foreach (array_values($where_values) as $k => $v) {
			$statement->bindValue($k+1, $v);
		}

		$exec_ret = $statement->execute();
		if (!$exec_ret) {
			error_log("ERROR CLASS:" . __CLASS__ . ", FUNCTION: " . __FUNCTION__ . ", LINE: " . __LINE__);
			error_log("ERROR - SQL FAILS: $sql");
			error_log("Parameters: " . print_r($where_values, TRUE));
			error_log(print_r($statement->errorInfo(), TRUE));
			return FALSE;
		}

		return $exec_ret;
	}

	public function deleteInstance($class_name, $id) {
		return $this->delete($class_name, "id=?", array($id));
	}
	
	public function insert(RecordObject $obj) {
		$table_name = $obj->getTableName();
		$db_handle = $this->getDbHandle();
		$list = get_object_vars($obj);

		$columns_sql = '('.join(',', array_keys($list)).')';
		
		$values = array();
		foreach (array_keys($list) as $k) {
			$values[] = ":$k";
		}
		$values_sql = '('.join(',', $values).')';
		$sql = "INSERT INTO `$table_name` $columns_sql VALUES $values_sql";
		$statement = $db_handle->prepare($sql);

		foreach ($list as $k => $v) {
			$statement->bindValue($k, $v);
		}

		$exec_ret = $statement->execute();
		if (!$exec_ret) {
			error_log("ERROR CLASS:" . __CLASS__ . ", FUNCTION: " . __FUNCTION__ . ", LINE: " . __LINE__);
			error_log("ERROR - SQL FAILS: $sql");
			error_log("Parameters: " . print_r($list, TRUE));
			error_log(print_r($statement->errorInfo(), TRUE));
			return -1;
		}

		return $db_handle->lastInsertId();
	}

	public function save_by_fields(RecordObject $obj, array $fields) {
		if ($obj->isNew()) {
			$ret = $this->insert($obj);
			return (in_array('id', $fields) && (count($fields) == 1)) ? $ret : ($ret == 0);
		}

		$table_name = $obj->getTableName();
		$obj = get_object_vars($obj);

		$set = array();
		foreach (array_keys($obj) as $k) {
			$set[] = "$k=:$k";
		}
		$set_sql = "SET ".join(',', $set);
		
		$where = array();
		foreach ($fields as $v) {
			$where[] = "$v=:_$v";
		}
		$where_sql = "WHERE ".join(' AND ', $where);

		$sql = "UPDATE `$table_name` $set_sql $where_sql";
		$statement = $this->getDbHandle()->prepare($sql);
		
		foreach ($obj as $k => $v) {
			$statement->bindValue($k, $v);
		}
		foreach ($fields as $v) {
			$statement->bindValue("_$v", $obj[$v]);
		}

		$exec_ret = $statement->execute();
		if (!$exec_ret) {
			error_log("ERROR CLASS:" . __CLASS__ . ", FUNCTION: " . __FUNCTION__ . ", LINE: " . __LINE__);
			error_log("ERROR - SQL FAILS: $sql");
			error_log("Parameters - Object: " . print_r($obj, TRUE));
			error_log("Parameters - Fields: " . print_r($fields, TRUE));
			error_log(print_r($statement->errorInfo(), TRUE));
			return FALSE;
		}

		return $exec_ret;
	}

	public function save(RecordObject $obj) {
		return $this->save_by_fields($obj, $obj->getPrimaryKey());
	}

}

?>
